package com.jeehentor.generate.generate.dbGenerate;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.jeehentor.generate.dto.GenerateDbDTO;
import com.jeehentor.generate.entity.SysGenModel;
import com.jeehentor.generate.entity.SysGenModelField;
import com.jeehentor.generate.generate.enums.GenerateModelType;
import com.jeehentor.generate.generate.enums.GenerateMysqlType;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class MysqlGenerateDb extends AbstractDbGenerate {

    @Override
    public List<String> generate(GenerateDbDTO generateDbDTO) {
        List<String> sqlList = new ArrayList<>();
        List<SysGenModelField> sysGenModelFields = generateDbDTO.getFieldList();
        if(GenerateModelType.CREATE_TABLE.getCode().equals(generateDbDTO.getModel())){
            //创建表
            sqlList.add(creteTable(generateDbDTO));
        }else if(GenerateModelType.UPDATE_TABLE_COMMENT.getCode().equals(generateDbDTO.getModel())){
            //修改备注
            sqlList.add("ALTER TABLE " + generateDbDTO.getSysGenModel().getTableName() + " COMMENT = " + "'" + generateDbDTO.getSysGenModel().getTableComment() + "'" + ";");
        }else if(GenerateModelType.CREATE_PRIMARY_KEY.getCode().equals(generateDbDTO.getModel())){
            //修改主键
            List<String> primaryKeyList = sysGenModelFields.stream().filter(x -> StringUtils.isNotBlank(x.getFieldName()) && "1".equals(x.getPrimaryKey())).sorted(Comparator.comparing(SysGenModelField::getSortOrder)).map(SysGenModelField::getFieldName).collect(Collectors.toList());
            StringBuilder primaryKeyBuilder = new StringBuilder();
            if(CollectionUtils.isNotEmpty(primaryKeyList)){
                primaryKeyList.forEach(x->{
                    primaryKeyBuilder.append("`").append(x).append("`,");
                });
                primaryKeyBuilder.deleteCharAt(primaryKeyBuilder.length() -1);
                sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName()+" ADD PRIMARY KEY (" + primaryKeyBuilder +");");
            }

        }else if(GenerateModelType.DELETE_PRIMARY_KEY.getCode().equals(generateDbDTO.getModel())){
            //删除表主键
            sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName()+" DROP PRIMARY KEY;");
        }else if(GenerateModelType.UPDATE_COLUMN_NAME.getCode().equals(generateDbDTO.getModel())){
            //修改表字段
            sqlList.addAll(updateColumnName(generateDbDTO));
        }else if(GenerateModelType.UPDATE_COLUMN_TYPE.getCode().equals(generateDbDTO.getModel())){
            //按顺序拼接
            sysGenModelFields.stream().sorted(Comparator.comparing(SysGenModelField::getSortOrder)).forEachOrdered(x->{
                //修改字段信息
                StringBuilder stringBuilder = new StringBuilder();
                modifyField(stringBuilder,x,GenerateModelType.UPDATE_TABLE_COMMENT.getCode());
                sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName() +" MODIFY " +stringBuilder +";");
            });
        }
        return sqlList;
    }

    /**
     * 创建表ddl
     * @param generateDbDTO
     * @return
     */
    private String creteTable(GenerateDbDTO generateDbDTO){
        SysGenModel sysGenModel = generateDbDTO.getSysGenModel();
        List<SysGenModelField> fieldList = generateDbDTO.getFieldList();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("CREATE TABLE ");
        //表名
        stringBuilder.append(sysGenModel.getTableName());
        stringBuilder.append("(");
        //按顺序拼接
        fieldList.stream().sorted(Comparator.comparing(SysGenModelField::getSortOrder)).forEachOrdered(x->{
            modifyField(stringBuilder,x,GenerateModelType.CREATE_TABLE.getCode());
        });
        //获取主键
        List<String> primaryKeyList = fieldList.stream().filter(x -> "1".equals(x.getPrimaryKey()) ).map(SysGenModelField::getFieldName).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(primaryKeyList)){
            stringBuilder.append("PRIMARY KEY (");
            primaryKeyList.forEach(x->{
                stringBuilder.append("`").append(x).append("`,");
            });
            stringBuilder.deleteCharAt(stringBuilder.length() -1);
            stringBuilder.append(") USING BTREE");
        }
        //不区分音调
        stringBuilder.append(") ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ");
        if(StringUtils.isNotBlank(sysGenModel.getTableComment())){
            stringBuilder.append("COMMENT='").append(sysGenModel.getTableComment()).append("';");
        }
        return stringBuilder.toString();
    }

    /**
     * 修改表字段
     * @param generateDbDTO
     * @return
     */
    private List<String> updateColumnName(GenerateDbDTO generateDbDTO){
        List<String> sqlList = new ArrayList<>();
        generateDbDTO.getFieldList().stream().sorted(Comparator.comparing(SysGenModelField::getSortOrder)).forEachOrdered(x->{
            if(StringUtils.isNotBlank(x.getFieldName()) && StringUtils.isNotBlank(x.getOldFieldName())){
                //修改字段信息
                StringBuilder stringBuilder = new StringBuilder();
                //列名
                stringBuilder.append("`").append(x.getOldFieldName()).append("`").append(" ");
                modifyField(stringBuilder,x,GenerateModelType.UPDATE_TABLE_COMMENT.getCode());
                sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName() +" CHANGE " +stringBuilder +";");
            }
            if(StringUtils.isNotBlank(x.getFieldName()) && StringUtils.isBlank(x.getOldFieldName())){
                //添加的字段信息
                StringBuilder stringBuilder = new StringBuilder();
                modifyField(stringBuilder,x,GenerateModelType.UPDATE_TABLE_COMMENT.getCode());
                sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName() +" ADD " +stringBuilder +";");

            }
            if(StringUtils.isBlank(x.getFieldName()) && StringUtils.isNotBlank(x.getOldFieldName())){
                //删除字段信息
                sqlList.add("ALTER TABLE "+ generateDbDTO.getSysGenModel().getTableName()+" DROP "+x.getOldFieldName()+";");
            }
        });
        return sqlList;
    }

    private void modifyField(StringBuilder stringBuilder,SysGenModelField x,String modelType){
        //列名
        stringBuilder.append("`").append(x.getFieldName()).append("`").append(" ");
        //有小数点单独判断
        if(GenerateMysqlType.doubleType.getCode().equals(x.getFieldType()) || GenerateMysqlType.BigDecimalType.getCode().equals(x.getFieldType())){
            stringBuilder.append(GenerateMysqlType.getDescByCode(x.getFieldType())).append("(").append(x.getLength()).append(",").append(x.getFieldPoint()).append(")").append(" ");
        }else {
            if(x.getLength() != null && (GenerateMysqlType.stringType.getCode().equals(x.getFieldType()) || GenerateMysqlType.BigDecimalType.getCode().equals(x.getFieldType()))){
                stringBuilder.append(GenerateMysqlType.getDescByCode(x.getFieldType())).append("(").append(x.getLength()).append(")").append(" ");
            }else {
                stringBuilder.append(GenerateMysqlType.getDescByCode(x.getFieldType())).append(" ");
            }
        }

        //是否可为空
        if(!"1".equals(x.getNullable())){
            stringBuilder.append("NOT NULL ");
        }
        //默认值
        if(StringUtils.isNotBlank(x.getDefaultValue())){
            if("CURRENT_TIMESTAMP".equals(x.getDefaultValue())){
                stringBuilder.append("DEFAULT ").append(x.getDefaultValue()).append(" ");
            }else {
                stringBuilder.append("DEFAULT '").append(x.getDefaultValue()).append("' ");
            }

        }
        //列注释
        if(GenerateModelType.CREATE_TABLE.getCode().equals(modelType)){
            if(StringUtils.isNotBlank(x.getRemarks())){
                stringBuilder.append("COMMENT '").append(x.getRemarks()).append("',");
            }
        }else {
            if(StringUtils.isNotBlank(x.getRemarks())){
                stringBuilder.append("COMMENT '").append(x.getRemarks()).append("'");
            }
        }

    }
}
